package com.whately.core.database.db;

import com.whately.core.base.annotation.WhDatabase;
import com.whately.core.database.vo.DatabaseTxPackageVO;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.interceptor.TransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionInterceptor;

import java.util.Map;
import java.util.regex.Pattern;

/**
 * 事务拦截器
 */
@Slf4j
public class WhatelyTxInterceptor extends TransactionInterceptor {
    //起个名字
    private String beanName;

    public WhatelyTxInterceptor(String beanName, TransactionManager ptm, TransactionAttributeSource tas) {
        this.beanName = beanName;
        super.setTransactionManager(ptm);
        super.setTransactionAttributeSource(tas);
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        //先指定为默认，防止之前的service遗留的值
        DynamicDataSourceContextHolder.set(DatabaseCfgConstant.DEFAULT_DATABASE_SCHEMA);

        WhDatabase whDatabase = invocation.getMethod().getAnnotation(WhDatabase.class);

        if(whDatabase!=null&&whDatabase.closeTx()){
            //关闭事务,直接进行方法调用，不开启事务
            //不开启事务，为dao或者mapper指定数据源
            if(whDatabase.dbName()!=null){
                DynamicDataSourceContextHolder.set(whDatabase.dbName());
            }
            return invocation.proceed();
        }

        //是否设定数据源
        if(whDatabase!=null&&StringUtils.isNotBlank(whDatabase.dbName())){
            DynamicDataSourceContextHolder.set(whDatabase.dbName());
        }

        if(DatabaseCfgConstant.TX_POINT_MAP.size()>0){
            //包名 com.whately.support.rbac.gw.user.service.impl
            String packagename=invocation.getMethod().getDeclaringClass().getPackage().getName();
            //截取 com.whately.support.rbac.gw.user.service
            if(packagename.endsWith(".impl")){
                packagename = packagename.substring(0,packagename.length()-5);
            }else{
                throw new RuntimeException("tx service impl package name not correct!");
            }

            DatabaseTxPackageVO packageModel = null;
            for (Map.Entry<String, DatabaseTxPackageVO> m : DatabaseCfgConstant.TX_POINT_MAP.entrySet()) {

                String patternStyle = m.getKey();
                if(Pattern.matches(patternStyle,packagename)){
                    packageModel = m.getValue();
                    break;
                }
            }

            if(packageModel!=null){
                if(packageModel.isTxClose()){
                    //关闭事务
                    //不开启事务，为dao或者mapper指定数据源
                    if(packageModel.getSchema()!=null){
                        DynamicDataSourceContextHolder.set(packageModel.getSchema());
                    }
                    return invocation.proceed();
                }

                DynamicDataSourceContextHolder.set(packageModel.getSchema());
            }
        }


        //默认开启事务
        return super.invoke(invocation);

    }

}
